﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SharedLib.MessageFramework;
using Tracy.DataModel;
using Tracy;
using System.IO;
using System.ComponentModel;
using SharedLib.Helpers;
using TracyGUI.UIComponent;
using SharedLib;
using System.Diagnostics;

namespace TracyGUI
{
    public partial class FormMain
    {

        /// <summary>
        /// Add new resource tab if not exist
        /// </summary>
        /// <param name="entryName">'All' - All Resources; 'New' - New Resources; Otherwise - Entry ID</param>
        private void AddFilesTab(string entryName, TabControl container, string parameter = null)
        {

            TabPageFiles newTab = new TabPageFiles(TabPageEntry.TABPAGE_NAME_FILES, TabPageEntry.TABPAGE_NAME_FILES, contextMenuStripFile);
            newTab.ListViewItems.MouseDoubleClick += new MouseEventHandler(listViewMediaFile_MouseDoubleClick);
            LoadDataToFileTab(newTab, entryName, parameter);
            container.TabPages.Add(newTab);
        }

        private void LoadDataToFileTab(TabPageFiles tab, string entryName, string parameter = null, bool clearView = true)
        {
            if (entryName == TabPageEntry.TABPAGE_NAME_ALL)
            {
                tab.LoadDataItemsToListView(TracyFacade.Instance.MediaFileProvider.GetItems(), clearView);
            }
            else if (entryName == TabPageEntry.TABPAGE_NAME_SEARCH)
            {
                tab.LoadDataItemsToListView(TracyFacade.Instance.SearchEngine.FileSearchResult, clearView);
            }
            //else if (entryName == TabPageEntry.TABPAGE_NAME_UE)
            //{
            //    tab.LoadDataItemsToListView(_ultraExplorerSelectedFiles, clearView);
            //}
            else
            {
                Entry entry = TracyFacade.Instance.EntryProvider.GetItemByID(entryName);
                tab.LoadDataItemsToListView(TracyFacade.Instance.MediaFileProvider.GetItemByEntry(entry), clearView);
            }
        }

        private void AddNewFile(MediaFile file)
        {
            if (file != null && file.Resource != null && file.Resource.Entry != null)
            {
                TracyFacade.Instance.MediaFileProvider.AddItem(file);
                string resEntryID = file.Resource.Entry.ID;
                foreach(TabPageEntry tabPage in GetRelatedEntryTabs(resEntryID))
                {
                    (tabPage.GetTabPage(TabPageEntry.TABPAGE_NAME_FILES) as TabPageFiles).AddDataItemToListView(file);
                }
            }
        }

        private void OnResourceMediaFilesAssigned(IAppMessage msg)
        {
            
            Resource res = msg.Data as Resource;
            List<MediaFile> files = msg.Result as List<MediaFile>;
            if (files != null && files.Count > 0)
            {
                foreach (MediaFile file in files)
                {
                    AddNewFile(file);
                }
            }
            //TODO: update entry (new item count)
        }

        private void InitMediaFiles()
        {

        }

        private void ChangeMediaFileStatus(MediaFile file, string newStatus)
        {
            if (file != null)
            {
                file.Status = newStatus;
                UpdateUIForMediaFileChange(file);
            }
        }

        private void UpdateUIForMediaFileChange(MediaFile file)
        {
            MediaFile oldFile = TracyFacade.Instance.MediaFileProvider.GetItemByID(file.ID);
            if (oldFile != null)
            {
                bool statusChanged = (oldFile.Status != file.Status);
                Entry entry = file.Resource.Entry;
                if (statusChanged)//won't update entry list if file status not got changed
                {
                    var removedItemInfo = BeginUpdateEntryInList(entry);
                    TracyFacade.Instance.MediaFileProvider.UpdateItem(file);
                    EndUpdateEntryInList(removedItemInfo);
                }
                else
                {
                    TracyFacade.Instance.MediaFileProvider.UpdateItem(file);
                }

                //Update entry tabs
                foreach (TabPageEntry entryTab in GetRelatedEntryTabs(entry.ID))
                {
                    if(entryTab.Name == entry.ID) entryTab.Text = entry.NameWithUnwatchedCount; //Update unwatched count
                    TabPageFiles fileTab = entryTab.GetTabPage(TabPageEntry.TABPAGE_NAME_FILES) as TabPageFiles;
                    if (fileTab != null)
                    {
                        fileTab.UpdateDataItem(file);
                    }
                }
            }
        }

        private List<MediaFile> GetSelectedFiles()
        {
            TabPageEntry entryTab = _tabControlContent.SelectedTab as TabPageEntry;
            TabPageFiles fileTab = entryTab.GetTabPage(TabPageEntry.TABPAGE_NAME_FILES) as TabPageFiles;
            if (fileTab != null)
            {
                return fileTab.GetSelectedDataItems();
            }
            return new List<MediaFile>();
        }

        private void listViewMediaFile_MouseDoubleClick(object sender, MouseEventArgs e)
        {

            List<MediaFile> selectedFiles = GetSelectedFiles();
            if (selectedFiles.Count > 0)
            {
                //Open the first item
                MediaFile file = selectedFiles[0];
                //TODO: Embeded player
                if (CheckFileAvailablity(file))
                {
                    System.Diagnostics.Process.Start(file.GetSavedFilePath());
                    if (file.Status != "Watched") ChangeMediaFileStatus(file, "Watched");
                }
            }
        }

        private bool CheckFileAvailablity(MediaFile file)
        {
            if (file.Status == "Ready" || file.Status == "Watched")
            {
                string filePath = file.GetSavedFilePath();
                if (filePath != null && File.Exists(filePath))
                {
                    return true;
                }
                else
                {
                    MessageBox.Show("File not found: " + filePath);
                    file.Properties[MediaFile.KEY_PREVIOUS_STATUS] = file.Status;
                    ChangeMediaFileStatus(file, "Missing");
                }
            }
            return false;
        }

        private void openWithToolStripMenuItem_MouseHover(object sender, EventArgs e)
        {
            List<MediaFile> selectedFiles = GetSelectedFiles();
            if (selectedFiles.Count == 1)
            {
                openWithToolStripMenuItem.DropDownItems.Clear();
                MediaFile selectedFile = selectedFiles[0];
                foreach (string appCmd in RegistryHelper.GetOpenWithList(selectedFile.GetFileExtension()))
                {
                    try
                    {
                        string appDesc = appCmd;
                        string[] args = Win32Helper.SplitArgs(appCmd);
                        if (args != null && args.Length > 0)
                        {
                            string appPath = args[0];
                            string desc = FileVersionInfo.GetVersionInfo(appPath).FileDescription;
                            if (!String.IsNullOrEmpty(desc))
                            {
                                appDesc = desc;
                            }
                            ToolStripItem openWithItem = openWithToolStripMenuItem.DropDownItems.Add(appDesc);

                            StringBuilder sbArgs = new StringBuilder();//Build up arguments string
                            for (int i = 1; i < args.Length; i++)
                            {
                                string tmp = args[i];
                                if(tmp == "%1") tmp = selectedFile.GetSavedFilePath();
                                if(tmp.Contains(" ") && !(tmp.StartsWith("\"") && tmp.StartsWith("\""))) tmp = "\"" + tmp + "\"";
                                sbArgs.Append(tmp);
                            }

                            ProcessStartInfo psi = new ProcessStartInfo(appPath, sbArgs.ToString());

                            openWithItem.Tag = psi;
                            openWithItem.Click += new EventHandler(openWithItem_Click);
                        }
                        
                    }
                    catch (Exception ex)
                    {
                        //Do Nothing
                    }
                }
                
            }
            
        }

        void openWithItem_Click(object sender, EventArgs e)
        {
            ToolStripItem item = sender as ToolStripItem;
            if (item != null)
            {
                ProcessStartInfo psi = item.Tag as ProcessStartInfo;
                if (psi != null)
                {
                    Process.Start(psi);
                    List<MediaFile> selectedFiles = GetSelectedFiles();
                    if (selectedFiles.Count > 0)
                    {
                        MediaFile file = selectedFiles[0];
                       if (file.Status != "Watched") ChangeMediaFileStatus(file, "Watched");
                    }
                }
            }
        }
        private void openContainingFolderToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<MediaFile> selectedFiles = GetSelectedFiles();
            if (selectedFiles.Count > 0)
            {
                //Open the first item
                MediaFile file = selectedFiles[0];
                System.Diagnostics.Process.Start(Path.GetDirectoryName(file.GetSavedFilePath()));
            }
        }

        private void contextMenuStripFile_Opening(object sender, CancelEventArgs e)
        {
            changeStatusToolStripMenuItem.Enabled = false;
            openWithToolStripMenuItem.Enabled = false;
            removeFileToolStripMenuItem.Enabled = false;
            openContainingFolderToolStripMenuItem.Enabled = false;
            List<MediaFile> selectedFiles = GetSelectedFiles();
            if (selectedFiles.Count > 0)
            {
                changeStatusToolStripMenuItem.Enabled = true;
                removeFileToolStripMenuItem.Enabled = true;
                openContainingFolderToolStripMenuItem.Enabled = true;

                if (selectedFiles.Count == 1)
                {
                    if(CheckFileAvailablity(selectedFiles[0])) openWithToolStripMenuItem.Enabled = true;
                }
            }
        }



        private void changeToWatchedStatusToolStripMenuItem_Click(object sender, EventArgs e)
        {

            List<MediaFile> selectedFiles = GetSelectedFiles();
            foreach (MediaFile file in selectedFiles)
            {
                ChangeMediaFileStatus(file, "Watched");
            }

        }

        private void changeToReadyStatusToolStripMenuItem_Click(object sender, EventArgs e)
        {
            List<MediaFile> selectedFiles = GetSelectedFiles();
            foreach (MediaFile file in selectedFiles)
            {
                ChangeMediaFileStatus(file, "Ready");
            }

        }

        private void removeFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TabPageEntry entryTab = _tabControlContent.SelectedTab as TabPageEntry;
            TabPageFiles fileTab = entryTab.GetTabPage(TabPageEntry.TABPAGE_NAME_FILES) as TabPageFiles;
            if (fileTab != null)
            {
                List<MediaFile> selectedFiles = fileTab.GetSelectedDataItems();
                RemoveMediaFilesAction(selectedFiles);
                fileTab.RemoveDataItems(selectedFiles);
            }
        }

        private void RemoveMediaFilesAction(List<MediaFile> filesToRemove)
        {
            List<string> physicalFilesToDelete = new List<string>();
            List<string> entriesToUpdate = new List<string>();
            List<dynamic> entrieRemoveInfoList = new List<dynamic>();
            StringWriter sw = new StringWriter();
            sw.Write("Do you want to remove the physical file(s) as well?");
            //Remove data
            foreach (MediaFile file in filesToRemove)
            {
                //_mappingMediaFile.Remove(file.ID);
                if (file.Status == "Ready" || file.Status == "Watched")
                {
                    physicalFilesToDelete.Add(file.GetSavedFilePath());
                    sw.Write("\r\n" + file.FileName);
                    if (file.Resource != null && file.Resource.Entry != null && !entriesToUpdate.Contains(file.Resource.Entry.ID))
                    {
                        entrieRemoveInfoList.Add(BeginUpdateEntryInList(file.Resource.Entry));
                        entriesToUpdate.Add(file.Resource.Entry.ID);
                    }
                }
                TracyFacade.Instance.MediaFileProvider.RemoveItem(file.ID);
            }

            //Update entry
            foreach (var removeInfo in entrieRemoveInfoList)
            {
                EndUpdateEntryInList(removeInfo);
            }

            //Delete physical file
            if (physicalFilesToDelete.Count > 0)
            {
                if (MessageBox.Show(sw.ToString(), "Delete File", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
                {
                    List<string> folders = new List<string>();
                    foreach (string filePath in physicalFilesToDelete)
                    {
                        if (filePath != null)
                        {
                            string path = Path.GetDirectoryName(filePath);
                            if (path != null && !folders.Contains(path))
                            {
                                folders.Add(path);
                            }
                            if (File.Exists(filePath))
                            {
                                File.Delete(filePath);
                            }
                        }
                    }

                    //Remove empty folders
                    foreach (string folder in folders)
                    {
                        IOHelper.DeleteFolderIfNotEmpty(folder);
                    }
                }
            }
        }
    }
}
